package chess_game_5;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

//子类，reversi模式
public class ReversiGame extends Game {
    private static final int[][] DIRECTIONS = {
            { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 },
            { -1, -1 }, { -1, 1 }, { 1, -1 }, { 1, 1 }
    };

    public ReversiGame(String player1, String player2, int gameId) {
        super(player1, player2, gameId, "reversi");
        calculateLegalMoves();
    }

    @Override
    public void initializeBoard() {
        board = new char[Chess.BOARD_SIZE][Chess.BOARD_SIZE];

        // foreach循环，用于遍历二维字符数组 board 的每一行。
        for (char[] row : board) {
            Arrays.fill(row, Chess.EMPTY);
        }
        // 初始棋子，reverci模式要求初始化棋盘的四个中心位置
        board[3][3] = Chess.PLAYER2_SYMBOL; // 4D
        board[3][4] = Chess.PLAYER1_SYMBOL; // 4E
        board[4][3] = Chess.PLAYER1_SYMBOL; // 5D
        board[4][4] = Chess.PLAYER2_SYMBOL; // 5E
    }

    @Override
    public boolean isValidMove(int row, int col) {
        if (board[row][col] != Chess.EMPTY)
            return false;
        char currentSymbol = player.isCurrentPlayer1() ? Chess.PLAYER1_SYMBOL : Chess.PLAYER2_SYMBOL;
        for (int[] dir : DIRECTIONS) {
            if (checkDirection(row, col, dir[0], dir[1], currentSymbol))
                return true;
        }
        return false;
    }

    // 检查指定方向是否存在可翻转的棋子链
    private boolean checkDirection(int row, int col, int dx, int dy, char symbol) {
        int x = row + dx;
        int y = col + dy;
        boolean hasOpponent = false;
        while (x >= 0 && x < Chess.BOARD_SIZE && y >= 0 && y < Chess.BOARD_SIZE) {
            if (board[x][y] == Chess.EMPTY)
                return false;
            if (board[x][y] == symbol)
                return hasOpponent;
            hasOpponent = true;
            x += dx;
            y += dy;
        }
        return false;
    }

    @Override
    public boolean placeChess(int row, int col) {
        if (!isValidMove(row, col))
            return false;
        char currentSymbol = player.isCurrentPlayer1() ? Chess.PLAYER1_SYMBOL : Chess.PLAYER2_SYMBOL;
        board[row][col] = currentSymbol;
        for (int[] dir : DIRECTIONS) {
            flipStones(row, col, dir[0], dir[1], currentSymbol);
        }
        player.switchPlayer();
        calculateLegalMoves();
        return true;
    }

    // 检查并翻转指定方向上的棋子
    private void flipStones(int row, int col, int dx, int dy, char symbol) {
        List<int[]> toFlip = new ArrayList<>();
        int x = row + dx;
        int y = col + dy;
        while (x >= 0 && x < Chess.BOARD_SIZE && y >= 0 && y < Chess.BOARD_SIZE) {
            if (board[x][y] == symbol) {
                for (int[] pos : toFlip) {
                    board[pos[0]][pos[1]] = symbol;
                }
                break;
            } else if (board[x][y] == Chess.EMPTY) {
                break;
            } else {
                toFlip.add(new int[] { x, y });
            }
            x += dx;
            y += dy;
        }
    }

    // 计算是否还存在合法落子位置
    private void calculateLegalMoves() {
        legalMoves.clear();
        for (int i = 0; i < Chess.BOARD_SIZE; i++) {
            for (int j = 0; j < Chess.BOARD_SIZE; j++) {
                if (isValidMove(i, j))
                    legalMoves.add(new int[] { i, j });
            }
        }
    }

    @Override
    public boolean isGameOver() {
        return legalMoves.isEmpty() || isBoardFull();
    }

    private boolean isBoardFull() {
        for (char[] row : board) {
            for (char cell : row) {
                if (cell == Chess.EMPTY)
                    return false;
            }
        }
        return true;
    }

    @Override
    public String getScoreInfo() {
        int black = 0, white = 0;
        for (char[] row : board) {
            for (char cell : row) {
                if (cell == Chess.PLAYER1_SYMBOL)
                    black++;
                else if (cell == Chess.PLAYER2_SYMBOL)
                    white++;
            }
        }
        return "● " + black + "  ○ " + white;
    }
}